package org.ns.tomdog.server.support;

import org.ns.tomdog.classloader.CommonClassLoader;
import org.ns.tomdog.classloader.WebAppClassLoader;
import org.ns.tomdog.config.WebConfig;
import org.ns.tomdog.search.FuzzySearch;
import org.ns.tomdog.server.HandlerWrapper;
import org.ns.tomdog.server.WebAppContext;
import org.ns.tomdog.servlet.HttpServlet;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class WebAppContextStartup implements WebAppContext {
    private String basePath;
    private String docPath;
    private String path;
    private String contextPath;
    private List<HandlerWrapper> handlerWrappers = new ArrayList<>();
    private Map<String, MapperWrapper> handlerWrapperMap = new ConcurrentHashMap<>();
    private FuzzySearch handlerWrapperSearch = new FuzzySearch();
    private CommonClassLoader commonClassLoader;

    public WebAppContextStartup(String basePath, String docPath, String contextPath, CommonClassLoader commonClassLoader) {

        if (!contextPath.endsWith("/")) {
            contextPath  = contextPath + "/";
        }
        if (!contextPath.startsWith("/")) {
            contextPath  = "/" + contextPath;
        }

        this.basePath = basePath;
        this.docPath = docPath;
        this.contextPath = contextPath;
        this.path = basePath + docPath; // /basePath/docPath/
        if (!path.endsWith("/")) {
            path = path + "/";
        }
        this.commonClassLoader = commonClassLoader;
    }

    @Override
    public MapperWrapper getHandlerWrapper(String url) {
        MapperWrapper mapperWrapper = handlerWrapperMap.get(url);
        if (mapperWrapper == null) {
            mapperWrapper = (MapperWrapper)handlerWrapperSearch.search(url);
            if (mapperWrapper != null) {
                handlerWrapperMap.put(url, mapperWrapper);
            }
        }

        return mapperWrapper;
    }

    @Override
    public String getContextPath() {
        return contextPath;
    }

    @Override
    public String getPath() {
        return path;
    }

    @Override
    public void init() {
        try {
            File webConfigPath = new File(path, "web.xml");
            Map<String, Class<?>> classMap = new HashMap<>();
            WebAppClassLoader classLoader = new WebAppClassLoader(path, classMap, commonClassLoader);
            WebConfig webConfig = new WebConfig(webConfigPath, classLoader);
            webConfig.parse();
            List<ServletWrapper> servletWrappers = webConfig.getServletWrappers();
            for (ServletWrapper servletWrapper : servletWrappers) {
                HttpServlet httpServlet = servletWrapper.getHttpServlet();
                List<String> mappers = servletWrapper.getMappers();
                this.handlerWrappers.add(servletWrapper);
                for (String mapper : mappers) {
                    handlerWrapperSearch.add(mapper, new MapperWrapper(httpServlet, mapper));
                }
            }
            for (HandlerWrapper handlerWrapper : this.handlerWrappers) {
                handlerWrapper.init();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void start() {
        for (HandlerWrapper handlerWrapper : this.handlerWrappers) {
            handlerWrapper.start();
        }
    }

}
